package com.dr.common.ution;



import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.DESedeKeySpec;




/**
 * Created by cq on 2015/3/17.
 */
public class RSATool {
	 	private final static String DES = "DES";  
	    private final static String CIPHER_ALGORITHM = "DES/ECB/NoPadding";
	    private final static String TriDes = "DESede/ECB/NoPadding";  
	    static byte[] key_all={(byte) 0x06,(byte) 0x13,(byte) 0x12,(byte) 0x23,(byte) 0x92,(byte) 0x98,(byte) 0x77,(byte) 0x39};
	    /** 
	     * DES 加密 
	     *  
	     * @param src 数据源 
	     * @param key 密钥，长度必须是8的倍数  用的其实只是8字节的秘钥
	     * @return 返回加密后的数据 
	     * @throws DesException 
	     */  
	    public static byte[] encrypt(byte[] src, byte[] key) {  
	        // DES算法要求有一个可信任的随机数源  
	        SecureRandom sr = new SecureRandom();  
	        try {  
	            // 从原始密匙数据创建DESKeySpec对象  
	            DESKeySpec dks = new DESKeySpec(key);  
	            // 创建一个密匙工厂，然后用它把DESKeySpec转换成  
	            // 一个SecretKey对象  
	            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);  
	            SecretKey securekey = keyFactory.generateSecret(dks);  
	            // Cipher对象实际完成加密操作,NoPadding为填充方式 默认为PKCS5Padding  
	            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);  
	            // 用密匙初始化Cipher对象  
	            cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);  
	            // 现在，获取数据并加密  
	            // 正式执行加密操作  
	            return cipher.doFinal(src);  
	        } catch (NoSuchAlgorithmException e) {  
	        	int x=0;
	             //LOG.error("算数错误", e);  
	        } catch (InvalidKeyException e) {  
	            // LOG.error("无效key错误", e);  
	        	int x=0;
	        } catch (InvalidKeySpecException e) {  
	            // LOG.error("无效key戳无", e); 
	        	int x=0;
	        } catch (NoSuchPaddingException e) {  
	            // LOG.error("填充错误", e);  
	        	int x=0;
	        } catch (IllegalBlockSizeException e) {  
	            // LOG.error("非法数据块", e); 
	        	int x=0;
	        } catch (BadPaddingException e) {  
	            // LOG.error("错误的填充", e);  
	        	int x=0;
	        }  
	        return null;  
	    }  
	  
	    /** 
	     * 生成密钥 
	     *  
	     * @return 
	     * @throws NoSuchAlgorithmException 
	     */  
	    public static byte[] initKey() throws NoSuchAlgorithmException {  
	        KeyGenerator kg = KeyGenerator.getInstance(DES);  
	        kg.init(56);  
	        SecretKey secretKey = kg.generateKey();  
	        return secretKey.getEncoded();  
	    }  
	  
	    /** 
	     * DES解密 
	     *  
	     * @param src 数据源 
	     * @param key 密钥，长度必须是8的倍数    用的其实只是8字节的秘钥
	     * @return 返回解密后的原始数据 
	     * @throws DesException 
	     * @throws Exception 
	     */  
	    public static byte[] decrypt(byte[] src, byte[] key) {  
	        // DES算法要求有一个可信任的随机数源  
	        SecureRandom sr = new SecureRandom();  
	        try {  
	            // 从原始密匙数据创建一个DESKeySpec对象  
	            DESKeySpec dks = new DESKeySpec(key);  
	            // 创建一个密匙工厂，然后用它把DESKeySpec对象转换成  
	            // 一个SecretKey对象  
	            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);  
	            SecretKey securekey = keyFactory.generateSecret(dks);  
	            // Cipher对象实际完成解密操作  
	            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);  
	            // 用密匙初始化Cipher对象  
	            cipher.init(Cipher.DECRYPT_MODE, securekey, sr);  
	            // 现在，获取数据并解密  
	            // 正式执行解密操作  
	            return cipher.doFinal(src);  
	        } catch (NoSuchAlgorithmException e) {  
//	            LOG.error("算数错误", e);  
	        } catch (InvalidKeyException e) {  
//	            LOG.error("无效key错误", e);  
	        } catch (InvalidKeySpecException e) {  
//	            LOG.error("无效key戳无", e);  
	        } catch (NoSuchPaddingException e) {  
//	            LOG.error("填充错误", e);  
	        } catch (IllegalBlockSizeException e) {  
//	            LOG.error("非法数据块", e);  
	        } catch (BadPaddingException e) {  
//	            LOG.error("错误的填充", e);  
	        }  
	        return null;  
	    }  
	    /******************
	     * 3DES 加密  
	     * @param data  输入数据  数据不为8的倍数，函数内部自动补0到8的倍数
	     * @param key	输入秘钥 16字节秘钥
	     * @return 输出加密后数据
	     *************/
	    public static byte[] trides_crypt(byte data[],byte key[]) {  
	        try {  
	            byte[] k = new byte[24];  
	  
	            int len = data.length;  
	            if(data.length % 8 != 0){  
	                len = data.length - data.length % 8 + 8;  
	            }  
	            byte [] needData = null;  
	            if(len != 0)  
	                needData = new byte[len];  
	              
	            for(int i = 0 ; i< len ; i++){  
	                needData[i] = 0x00;  
	            }  
	              
	            System.arraycopy(data, 0, needData, 0, data.length);  
	              
	            if (key.length == 16) {  
	                System.arraycopy(key, 0, k, 0, key.length);  
	                System.arraycopy(key, 0, k, 16, 8);  
	            } else {  
	                System.arraycopy(key, 0, k, 0, 24);  
	            }  
	  
	            KeySpec ks = new DESedeKeySpec(k);  
	            SecretKeyFactory kf = SecretKeyFactory.getInstance("DESede");  
	            SecretKey ky = kf.generateSecret(ks);  
	  
	            Cipher c = Cipher.getInstance(TriDes);  
	            c.init(Cipher.ENCRYPT_MODE, ky);  
	            return c.doFinal(needData);  
	        } catch (Exception e) {  
	            e.printStackTrace();  
	            return null;  
	        }  
	  
	    }  
	    /**************
	     * 3DES 解密
	     * @param data 输入数据  数据不为8的倍数，函数内部自动补0到8的倍数
	     * @param key 16字节秘钥
	     * @return
	     */
	    public static byte[] trides_decrypt(byte data[],byte key[]) {  
	        try {  
	            byte[] k = new byte[24];  

	            int len = data.length;  
	            if(data.length % 8 != 0){  
	                len = data.length - data.length % 8 + 8;  
	            }  
	            byte [] needData = null;  
	            if(len != 0)  
	                needData = new byte[len];  
	              
	            for(int i = 0 ; i< len ; i++){  
	                 needData[i] = 0x00;  
	             }  
	               
	             System.arraycopy(data, 0, needData, 0, data.length);  
	               
	             if (key.length == 16) {  
	                 System.arraycopy(key, 0, k, 0, key.length);  
	                 System.arraycopy(key, 0, k, 16, 8);  
	             } else {  
	                 System.arraycopy(key, 0, k, 0, 24);  
	             }  
	             KeySpec ks = new DESedeKeySpec(k);  
	             SecretKeyFactory kf = SecretKeyFactory.getInstance("DESede");  
	             SecretKey ky = kf.generateSecret(ks);  
	   
	             Cipher c = Cipher.getInstance(TriDes);  
	             c.init(Cipher.DECRYPT_MODE, ky);  
	             return c.doFinal(needData);  
	         } catch (Exception e) {  
	             e.printStackTrace();  
	             return null;  
	         }  
	   
	     }  
	    
	    /////////////////////////////////////
	    
	    public static byte[] IV = new byte[8];

		public static byte byteXOR(byte src, byte src1) {
			return (byte) ((src & 0xFF) ^ (src1 & 0xFF));
		}

		public static byte[] bytesXOR(byte[] src, byte[] src1) {
			int length = src.length;
			if (length != src1.length) {
				return null;
			}
			byte[] result = new byte[length];
			for (int i = 0; i < length; i++) {
				result[i] = byteXOR(src[i], src1[i]);
			}
			return result;
		}

		/**
		 * mac计算,数据不为8的倍数，需要补0，将数据8个字节进行异或，再将异或的结果与下一个8个字节异或，一直到最后，将异或后的数据进行DES计算
		 * 
		 * @param key
		 * @param Input
		 * @return
		 */
		public static byte[] clacMac(byte[] key, byte[] Input) {
			int length = Input.length;
			int x = length % 8;
			int addLen = 0;
			if (x != 0) {
				addLen = 8 - length % 8;
			}
			int pos = 0;
			byte[] data = new byte[length + addLen];
			System.arraycopy(Input, 0, data, 0, length);
			byte[] oper1 = new byte[8];
			System.arraycopy(data, pos, oper1, 0, 8);
			pos += 8;
			for (int i = 1; i < data.length / 8; i++) {
				byte[] oper2 = new byte[8];
				System.arraycopy(data, pos, oper2, 0, 8);
				byte[] t = bytesXOR(oper1, oper2);
				oper1 = t;
				pos += 8;
			}
			// 将异或运算后的最后8个字节（RESULT BLOCK）转换成16个HEXDECIMAL：
			byte[] resultBlock = bytesToHexString(oper1).getBytes();
			// 取前8个字节用mkey1，DES加密
			byte[] front8 = new byte[8];
			System.arraycopy(resultBlock, 0, front8, 0, 8);
			byte[] behind8 = new byte[8];
			System.arraycopy(resultBlock, 8, behind8, 0, 8);
			byte[] desfront8 = encrypt(front8, key);
			// 将加密后的结果与后8 个字节异或：
			byte[] resultXOR = bytesXOR(desfront8, behind8);
			// 用异或的结果TEMP BLOCK 再进行一次单倍长密钥算法运算
			byte[] buff = encrypt(resultXOR, key);
			// 将运算后的结果（ENC BLOCK2）转换成16 个HEXDECIMAL asc
			// 取8个长度字节
			byte[] retBuf = new byte[8];
			System.arraycopy(bytesToHexString(buff).getBytes(), 0, retBuf, 0, 8);
			return retBuf;
		}
		
		public static byte[] clacMac(byte[] Input) {
			int length = Input.length;
			int x = length % 8;
			int addLen = 0;
			if (x != 0) {
				addLen = 8 - length % 8;
			}
			int pos = 0;
			byte[] data = new byte[length + addLen];
			System.arraycopy(Input, 0, data, 0, length);
			byte[] oper1 = new byte[8];
			System.arraycopy(data, pos, oper1, 0, 8);
			pos += 8;
			for (int i = 1; i < data.length / 8; i++) {
				byte[] oper2 = new byte[8];
				System.arraycopy(data, pos, oper2, 0, 8);
				byte[] t = bytesXOR(oper1, oper2);
				oper1 = t;
				pos += 8;
			}
			// 将异或运算后的最后8个字节（RESULT BLOCK）转换成16个HEXDECIMAL：
			byte[] resultBlock = bytesToHexString(oper1).getBytes();
			// 取前8个字节用mkey1，DES加密
			byte[] front8 = new byte[8];
			System.arraycopy(resultBlock, 0, front8, 0, 8);
			byte[] behind8 = new byte[8];
			System.arraycopy(resultBlock, 8, behind8, 0, 8);
			byte[] desfront8 = encrypt(front8, key_all);
			// 将加密后的结果与后8 个字节异或：
			byte[] resultXOR = bytesXOR(desfront8, behind8);
			// 用异或的结果TEMP BLOCK 再进行一次单倍长密钥算法运算
			byte[] buff = encrypt(resultXOR, key_all);
			// 将运算后的结果（ENC BLOCK2）转换成16 个HEXDECIMAL asc
			// 取8个长度字节
			byte[] retBuf = new byte[8];
			System.arraycopy(bytesToHexString(buff).getBytes(), 0, retBuf, 0, 8);
			return retBuf;
		}
		
		public static final String bytesToHexString(byte[] bArray) {
			StringBuffer sb = new StringBuffer(bArray.length);
			String sTemp;
			for (int i = 0; i < bArray.length; i++) {
				sTemp = Integer.toHexString(0xFF & bArray[i]);
				if (sTemp.length() < 2)
					sb.append(0);
				sb.append(sTemp.toUpperCase());
			}
			return sb.toString();
		}
}